/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.ui;

import java.awt.*;
import java.awt.event.MouseEvent;

import javax.swing.*;
import javax.swing.event.ListSelectionListener;

import com.pearreview.application.Messages;

/**
 * StepTabs
 * @author Dimitrij Pankratz, Anton Musichin
 *
 */
public class StepTabs extends JPanel {
	
	private static final long serialVersionUID = 3358157301616893098L;
	
	public static final int UNCHECKED_STATE = 0;
	public static final int CHECKED_STATE = 1;
	public static final int ERROR_STATE = 2;
	
	private ShadowLabel tabCaption;
	private Tabs tabs;
	private String[] steps;
	private ApplicationListCellRenderer renderer;
	private TabListSelectionModel selectionModel = new TabListSelectionModel();

	/**
	 * 
	 * @param steps
	 * @param tabListener
	 */
	public StepTabs(String[] steps) {
		this.steps = steps;
		initComponents();
	}
	
	/**
	 * Sets the tabs to enabled or disabled beginning from given index.
	 * While enabling, the index is ignored.
	 * 
	 * @param enabled
	 * @param index
	 */
	public void setMaxSelectionIndex(int index) {
		selectionModel.setUpperIndexLimit(index);
	}
	
	public int getMaxSelectionIndex() {
		return selectionModel.getUpperIndexLimit();
	}
	
	public void setSelectedIndex(int index) {
		tabs.setSelectedIndex(index);
	}
	
	public int getSelectedIndex() {
		return tabs.getSelectedIndex();
	}
	
	private void initComponents() {
		tabs = new Tabs(steps);
		tabs.setSelectionModel(selectionModel);
		renderer = new ApplicationListCellRenderer();
		tabs.setCellRenderer(renderer);
		tabs.setBorder(null);
		
		tabCaption = new ShadowLabel();

		//======== this ========
		setBackground(Color.gray);

		//---- tabCaption ----
		tabCaption.setText(Messages.getString("PearReview.steptabs.caption"));
		tabCaption.setFont(new Font("Tahoma", Font.PLAIN, 12));
		tabCaption.setForeground(new Color(0x222222));
		tabCaption.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		tabCaption.setHorizontalAlignment(SwingConstants.LEFT);
		tabCaption.setVerticalAlignment(SwingConstants.CENTER);
		tabCaption.setShadowColor(new Color(0x999999));
		
		tabs.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tabs.setBackground(Color.gray);
		
		GroupLayout layout = new GroupLayout(this);
		setLayout(layout);
		layout.setHorizontalGroup(
			layout.createParallelGroup()
				.addComponent(tabCaption, 
						GroupLayout.DEFAULT_SIZE, 
						GroupLayout.DEFAULT_SIZE, 
						Short.MAX_VALUE)
				.addComponent(tabs, 
						GroupLayout.DEFAULT_SIZE, 
						0, 
						Short.MAX_VALUE)
		);
		layout.setVerticalGroup(
			layout.createParallelGroup()
				.addGroup(layout.createSequentialGroup()
					.addComponent(tabCaption, 
							GroupLayout.PREFERRED_SIZE, 
							GroupLayout.DEFAULT_SIZE, 
							GroupLayout.PREFERRED_SIZE)
					.addComponent(tabs, 
							GroupLayout.DEFAULT_SIZE, 
							0, 
							Short.MAX_VALUE))
		);
	}
	
	public void addListSelectionListener(ListSelectionListener lsl) {
		tabs.getSelectionModel().addListSelectionListener(lsl);
	}
	
	public void removeListSelectionListener(ListSelectionListener lsl) {
		tabs.getSelectionModel().removeListSelectionListener(lsl);
	}
	
	private class TabListSelectionModel extends DefaultListSelectionModel {
		private static final long serialVersionUID = -7237515855282506737L;
		
		private int maxIndex = -1;
		
		public void setUpperIndexLimit(int index) {
			maxIndex = index;
			setSelectionInterval(getMinSelectionIndex(), 
					getMaxSelectionIndex());
		}
		
		public int getUpperIndexLimit() {
			return maxIndex;
		}
		
		@Override
		public void setSelectionInterval(int index0, int index1) {
			
			if(getMinSelectionIndex() == index0 
					&& getMaxSelectionIndex() == index1) {
				// do nothing
			} else if(maxIndex < 0) {
				super.setSelectionInterval(index0, index1);
			} else {
				int index0Min = Math.min(index0, maxIndex);
				int index1Min = Math.min(index1, maxIndex);
				super.setSelectionInterval(index0Min, index1Min);
			}
		}
	}
	
	/**
	 * Sets the tooltip with the given text for the tab on given index.
	 * 
	 * @param text
	 * @param index
	 */
	public void setToolTipTab(String text, int index) {
		tabs.setToolTipAt(text, index);
	}
	
	/**
	 * Sets the tab on given index to checked.
	 * 
	 * @param index
	 */
	public void setTabChecked(int index) {
		tabs.setChecked(index);
	}
	
	/**
	 * Sets the tab on given index to unchecked.
	 * 
	 * @param index
	 */
	public void setTabUnchecked(int index) {
		tabs.setUnchecked(index);
	}
	
	/**
	 * Marks the tab on given index with an error icon.
	 * 
	 * @param index
	 */
	public void setTabError(int index) {
		tabs.setError(index);
	}
	
	public void setStates(Integer[] states) {
		tabs.setStates(states);
	}
	
	public Integer[] getStates() {
		return tabs.getStates();
	}
	
	/**
	 * Returns the state value for a valid tab index otherwise -1.
	 * 
	 * @param index
	 * @return
	 */
	public int getTabState(int index) {
		return tabs.getState(index);
	}
	
	public void setTabState(int index, int state) {
		tabs.setState(index, state);
	}
	
	private static class ApplicationListCellRenderer 
			extends DefaultListCellRenderer {
		private static final long serialVersionUID = 3777355192749654883L;

		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {
			StepTabPanel c = new StepTabPanel();
			c.setPreferredSize(new Dimension(0, 35));
			c.setLayout(new BorderLayout());
			String element = (String) value;
			if(cellHasFocus) {
				element = "<u>" + element + "</u>";
			}
			element = "<html>" + element + "</html>";
			if (index == 0) {
				c.setFirst(true);
			}

			JLabel label = new JLabel(element);
			label.setForeground(new Color(0xe7e7e7));
			label.setFont(new Font("Tahoma", Font.PLAIN, 12));
			label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
			
			Tabs tabs = (Tabs)list;
			switch (tabs.getState(index)) {
			case StepTabs.CHECKED_STATE: 
				label.setIcon(new ImageIcon(getClass().getResource(
						"images/checked.png")));
				break;
			case StepTabs.ERROR_STATE: 
				label.setIcon(new ImageIcon(getClass().getResource(
						"images/checked_error.png")));
				break;
			default: 
				label.setIcon(new ImageIcon(getClass().getResource(
						"images/unchecked.png")));
				break;
			}
			
			c.add(label,BorderLayout.CENTER);
			
			TabListSelectionModel selectionModel = 
					(TabListSelectionModel)list.getSelectionModel();
			
			int maxIndex = selectionModel.getUpperIndexLimit();
			
			if (maxIndex < index && maxIndex >= 0) {
				label.setForeground(new Color(0xa9a9a9));
			}
			
			c.setSelected(isSelected);
			
			if(isSelected) {
				label.setForeground(new Color(0x333333));
			}
			
			return c;
		}   
	}
	
	private class Tabs extends JList {

		private static final long serialVersionUID = -4228304757721149028L;
		private String[] toolTips;
		private Integer[] state;
		
		public Tabs(String[] data) {
			super(data);
			toolTips = new String[data.length];
			state = new Integer[data.length];
			for (int i=0; i<data.length; i++) {
				state[i] = 0;
			}
			ToolTipManager.sharedInstance().registerComponent(this);
		}
		
		public void setUnchecked(int index) {
			setState(index, StepTabs.UNCHECKED_STATE);
		}
		
		public void setChecked(int index) {
			setState(index, StepTabs.CHECKED_STATE);
		}
		
		public void setError(int index) {
			setState(index, StepTabs.ERROR_STATE);
		}
		
		public void setState(int index, int newState) {
			if (index < state.length && index >= 0)
				state[index] = newState;
			
			repaint();
		}
		
		public int getState(int index) {
			if (index < state.length && index >= 0)
				return state[index];
			return -1;
		}
		
		public void setStates(Integer[] states) {
			for(int i = 0 ; i < states.length ; i++) {
				setState(i, states[i]);
			}
		}
		
		public Integer[] getStates() {
			return state;
		}
		
		public void setToolTipAt(String text, int index) {
			if (index < toolTips.length && index >= 0)
				toolTips[index] = text;
		}
		
		@Override
		public String getToolTipText(MouseEvent event) {
		    Point p = event.getPoint();
		    return toolTips[locationToIndex(p)];
		}
		
	}
}